---
title: "Range Calendar"
description: "The Range Calendar component is used to display one or more date grids and allows users to select a contiguous range of dates."
---

import {rangeCalendarContent} from "@/content/components/range-calendar";

# Range Calendar

A range calendar consists of a grouping element containing one or more date grids (e.g. months), and a previous and next button for navigating through time. Each calendar grid consists of cells containing button elements that can be pressed and navigated to using the arrow keys to select a date range. Once a start date is selected, the user can navigate to another date using the keyboard or by hovering over it, and clicking it or pressing the Enter key commits the selected date range.

<ComponentLinks component="calendar" storybook="rangecalendar" reactAriaHook="useCalendar" />

---

<CarbonAd/>

## Installation

<PackageManagers
  showGlobalInstallWarning
  commands={{
    cli: "npx heroui-cli@latest add calendar",
    npm: "npm install @heroui/calendar",
    yarn: "yarn add @heroui/calendar",
    pnpm: "pnpm add @heroui/calendar",
    bun: "bun add @heroui/calendar",
  }}
/>

## Import

<ImportTabs
  commands={{
    main: 'import {RangeCalendar} from "@heroui/react";',
    individual: 'import {RangeCalendar} from "@heroui/calendar";',
  }}
/>

## Usage

A RangeCalendar has no selection by default. An initial, uncontrolled value can be provided to the RangeCalendar using the `defaultValue` prop. Alternatively, a controlled value can be provided using the `value` prop.

Date values are provided using objects in the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/) package. This library handles correct international date manipulation across calendars, time zones, and other localization concerns.

<CodeDemo title="Usage" files={rangeCalendarContent.usage} />

### Disabled

The `isDisabled` boolean prop makes the Calendar disabled. Cells cannot be focused or selected.

<CodeDemo title="Disabled" files={rangeCalendarContent.disabled} />

### Read Only

The `isReadOnly` boolean prop makes the Calendar's value immutable. Unlike `isDisabled`, the Calendar remains focusable.

<CodeDemo title="Read Only" files={rangeCalendarContent.readonly} />

### Controlled

A Calendar has no selection by default. An initial, uncontrolled value can be provided to the Calendar using the `defaultValue` prop. Alternatively, a controlled value can be provided using the value prop.

<CodeDemo title="Controlled" files={rangeCalendarContent.controlled} />

### Min Date Value

By default, Calendar allows selecting any date. The `minValue` can also be used to prevent the user from selecting dates outside a certain range.

This example only accepts dates after today.

<CodeDemo title="Min Date Value" files={rangeCalendarContent.minDateValue} />

### Max Date Value

By default, Calendar allows selecting any date. The `maxValue` can also be used to prevent the user from selecting dates outside a certain range.

This example only accepts dates before today.

<CodeDemo title="Max Date Value" files={rangeCalendarContent.maxDateValue} />

### Unavailable Dates

Calendar supports marking certain dates as unavailable. These dates remain focusable with the keyboard so that navigation is consistent, but cannot be selected by the user. In this example, they are displayed in red. The `isDateUnavailable` prop accepts a callback that is called to evaluate whether each visible date is unavailable.

<CodeDemo title="Unavailable Dates" files={rangeCalendarContent.unavailableDates} />

### Non-Contiguous Ranges

The `allowsNonContiguousRanges` prop enables a range to be selected even if there are unavailable dates in the middle. The value emitted in the onChange event will still be a single range with a start and end property, but unavailable dates will not be displayed as selected. It is up to applications to split the full selected range into multiple as needed for business logic.

This example prevents selecting weekends, but allows selecting ranges that span multiple weeks.

<CodeDemo title="Unavailable Dates" files={rangeCalendarContent.nonContiguousRanges} />

### Controlled Focused Value

Calendar tries to avoid allowing the user to select invalid dates in the first place. However, if according to application logic a selected date is invalid, the isInvalid prop can be set. This alerts assistive technology users that the selection is invalid, and can be used for styling purposes as well. In addition, the errorMessage slot may be used to help the user fix the issue.

By default, the selected date is focused when a Calendar first mounts. If no `value` or `defaultValue` prop is provided, then the current date is focused. However, Calendar supports controlling which date is focused using the `focusedValue` and `onFocusChange` props. This also determines which month is visible. The `defaultFocusedValue` prop allows setting the initial focused date when the Calendar first mounts, without controlling it.

<CodeDemo title="Controlled Focused Value" files={rangeCalendarContent.controlledFocusedValue} />

### Invalid Date

This example validates that the selected date is a weekday and not a weekend according to the current locale.

<CodeDemo title="Invalid Date" files={rangeCalendarContent.invalidDate} />

### With Month And Year Picker

Calendar supports month and year picker for rapid selection. You can enable this feature by setting `showMonthAndYearPickers` to `true`. However, if `visibleMonths` is set to a number greater than 1, this feature will be disabled.

<CodeDemo title="With Month And Year Picker" files={rangeCalendarContent.withMonthAndYearPicker} />

### International Calendars

Calendar supports selecting dates in many calendar systems used around the world, including Gregorian, Hebrew, Indian, Islamic, Buddhist, and more. Dates are automatically displayed in the appropriate calendar system for the user's locale. The calendar system can be overridden using the [Unicode calendar locale extension](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/calendar#adding_a_calendar_in_the_locale_string), passed to the `Provider` component.

<CodeDemo title="International Calendars" files={rangeCalendarContent.internationalCalendars} />

### Visible Months

By default, the Calendar displays a single month. The `visibleMonths` prop allows displaying up to 3 months at a time.

<CodeDemo title="Visible Months" files={rangeCalendarContent.visibleMonths} />

### Custom first day of week

By default, the first day of the week is automatically set based on the current locale. This can be changed by setting the `firstDayOfWeek` prop to `'sun'`, `'mon'`, `'tue'`, `'wed'`, `'thu'`, `'fri'`, or `'sat'`.

<CodeDemo title="Custom first day of week" files={rangeCalendarContent.firstDayOfWeek} />

### Page Behaviour

By default, when pressing the next or previous buttons, pagination will advance by the `visibleMonths` value. This behavior can be changed to page by single months instead, by setting `pageBehavior` to `single`.

<CodeDemo title="Page Behaviour" files={rangeCalendarContent.pageBehaviour} />

### Presets

Here's the example to customize `topContent` and `bottomContent` to have some preset values.

<CodeDemo title="Presets" files={rangeCalendarContent.presets} />

## Slots

- **base**: Calendar wrapper, it handles alignment, placement, and general appearance.
- **prevButton**: The previous button of the calendar.
- **nextButton**: The next button of the calendar.
- **headerWrapper**: Wraps the picker (month / year).
- **header**: The header element.
- **title**: A description of the visible date range, for use in the calendar title.
- **gridWrapper**: The wrapper for the calendar grid.
- **grid**: The date grid element (e.g. `<table>`).
- **gridHeader**: The date grid header element (e.g. `<th>`).
- **gridHeaderRow**: The date grid header row element (e.g. `<tr>`).
- **gridHeaderCell**: The date grid header cell element (e.g. `<td>`).
- **gridBody**: The date grid body element (e.g. `<tbody>`).
- **gridBodyRow**: The date grid body row element (e.g. `<tr>`).
- **cell**: The date grid cell element (e.g. `<td>`).
- **cellButton**: The button element within the cell.
- **pickerWrapper**: The wrapper for the picker
- **pickerMonthList**: The month list picker.
- **pickerYearList**: The year list picker.
- **pickerHighlight**: The highlighted item of the picker.
- **pickerItem**: The item of the picker.
- **helperWrapper**: The helper message of the calendar.
- **errorMessage**: The error message of the calendar.

<Spacer y={4} />

## Data Attributes

`Calendar` has the following attributes on the `CalendarCell` element:

- **data-focused**:
  Whether the cell is focused.
- **data-hovered**:
  Whether the cell is currently hovered with a mouse.
- **data-pressed**:
  Whether the cell is currently being pressed.
- **data-unavailable**:
  Whether the cell is unavailable, according to the calendar's `isDateUnavailable` prop. Unavailable dates remain focusable, but cannot be selected by the user. They should be displayed with a visual affordance to indicate they are unavailable, such as a different color or a strikethrough.
- **data-disabled**:
  Whether the cell is disabled, according to the calendar's `minValue`, `maxValue`, and `isDisabled` props.
- **data-focus-visible**:
  Whether the cell is keyboard focused.
- **data-outside-visible-range**:
  Whether the cell is outside the visible range of the calendar.
- **data-outside-month**:
  Whether the cell is outside the current month.
- **data-selected**:
  Whether the cell is selected.
- **data-selected-start**:
  Whether the cell is the first date in a range selection.
- **data-selected-end**:
  Whether the cell is the last date in a range selection.
- **data-invalid**:
  Whether the cell is part of an invalid selection.

<Spacer y={4} />

## Accessibility

- Display one or more months at once, or a custom time range for use cases like a week view. Minimum and maximum values, unavailable dates, and non-contiguous selections are supported as well.
- Support for 13 calendar systems used around the world, including Gregorian, Buddhist, Islamic, Persian, and more. Locale-specific formatting, number systems, and right-to-left support are available as well.
- Calendar cells can be navigated and selected using the keyboard, and localized screen reader messages are included to announce when the selection and visible date range change.

<Spacer y={4} />

## API

### RangeCalendar Props

<APITable
  data={[
    {
      attribute: "value",
      type: "RangeValue",
      description: "The current value (controlled).",
      default: "null"
    },
    {
      attribute: "defaultValue",
      type: "RangeValue",
      description: "The default value (uncontrolled).",
      default: "null"
    },
    {
      attribute: "minValue",
      type: "DateValue",
      description: "The minimum allowed date that a user may select.",
      default: "-"
    },
    {
      attribute: "maxValue", 
      type: "DateValue",
      description: "The maximum allowed date that a user may select.",
      default: "-"
    },
    {
      attribute: "color",
      type: "default | primary | secondary | success | warning | danger",
      description: "The color of the time input.",
      default: "default"
    },
    {
      attribute: "visibleMonths",
      type: "number",
      description: "The number of months to display at once. Up to 3 months are supported. Passing a number greater than 1 will disable the showMonthAndYearPickers prop.",
      default: "1"
    },
    {
      attribute: "firstDayOfWeek",
      type: "sun | mon | tue | wed | thu | fri | sat",
      description: "The day that starts the week.",
      default: "-"
    },
    {
      attribute: "selectionAlignment",
      type: "start | center | end",
      description: "Determines the alignment of the visible months on initial render based on the current selection or current date if there is no selection.",
      default: "center"
    },
    {
      attribute: "focusedValue",
      type: "DateValue",
      description: "Controls the currently focused date within the calendar.",
      default: "-"
    },
    {
      attribute: "defaultFocusedValue",
      type: "DateValue", 
      description: "The date that is focused when the calendar first mounts (uncountrolled).",
      default: "-"
    },
    {
      attribute: "calendarWidth",
      type: "number | string",
      description: "The width to be applied to the calendar component. This value is multiplied by the visibleMonths number to determine the total width of the calendar.",
      default: "256"
    },
    {
      attribute: "pageBehavior",
      type: "PageBehavior",
      description: "Controls the behavior of paging. Pagination either works by advancing the visible page by visibleDuration (default) or one unit of visibleDuration.",
      default: "visible"
    },
    {
      attribute: "weekdayStyle",
      type: "narrow | short | long",
      description: "The style of weekday names to display in the calendar grid header.",
      default: "narrow"
    },
    {
      attribute: "showMonthAndYearPickers",
      type: "boolean",
      description: "Whether to show month and year pickers.",
      default: "false"
    },
    {
      attribute: "allowsNonContiguousRanges",
      type: "boolean",
      description: "When combined with isDateUnavailable, determines whether non-contiguous ranges, i.e. ranges containing unavailable dates, may be selected.",
      default: "false"
    },
    {
      attribute: "isDisabled",
      type: "boolean",
      description: "Whether the calendar is disabled.",
      default: "false"
    },
    {
      attribute: "isReadOnly",
      type: "boolean",
      description: "Whether the calendar value is immutable.",
      default: "false"
    },
    {
      attribute: "isInvalid",
      type: "boolean",
      description: "Whether the current selection is invalid according to application logic.",
      default: "-"
    },
    {
      attribute: "autoFocus",
      type: "boolean",
      description: "Whether to automatically focus the calendar when it mounts.",
      default: "false"
    },
    {
      attribute: "showHelper",
      type: "boolean",
      description: "Whether to show the description or error message.",
      default: "false"
    },
    {
      attribute: "showShadow",
      type: "boolean",
      description: "Whether to show the shadow in the selected dates.",
      default: "false"
    },
    {
      attribute: "topContent",
      type: "ReactNode",
      description: "Custom content to be included in the top of the calendar.",
      default: "-"
    },
    {
      attribute: "bottomContent",
      type: "ReactNode",
      description: "Custom content to be included in the bottom of the calendar.",
      default: "-"
    },
    {
      attribute: "isDateUnavailable",
      type: "(date: DateValue) => boolean",
      description: "Callback that is called for each date of the calendar. If it returns true, then the date is unavailable.",
      default: "-"
    },
    {
      attribute: "createCalendar",
      type: "(calendar: SupportedCalendars) => Calendar | null",
      description: "This function helps to reduce the bundle size by providing a custom calendar system.",
      default: "all calendars"
    },
    {
      attribute: "errorMessage",
      type: "ReactNode | (v: ValidationResult) => ReactNode",
      description: "An error message for the field.",
      default: "-"
    },
    {
      attribute: "validate",
      type: "(value: { inputValue: string, selectedKey: React.Key }) => ValidationError | true | null | undefined",
      description: "Validate input values when committing (e.g. on blur), returning error messages for invalid values.",
      default: "-"
    },
    {
      attribute: "hideDisabledDates",
      type: "boolean",
      description: "Whether to hide the disabled or invalid dates.",
      default: "false"
    },
    {
      attribute: "disableAnimation",
      type: "boolean",
      description: "Whether to disable the animation of the calendar.",
      default: "false"
    }
  ]}
/>

### RangeCalendar Events

<APITable
  data={[
    {
      attribute: "onFocusChange",
      type: "(date: CalendarDate) => void",
      description: "Handler that is called when the focused date changes.",
      default: "-"
    },
    {
      attribute: "onChange",
      type: "(value: RangeValue<DateValue> | null) => void",
      description: "Handler that is called when the value changes.",
      default: "-"
    }
  ]}
/>

#### Supported Calendars

```ts
/**
 * Supported react-aria i18n calendars.
 */
export type SupportedCalendars =
  | "buddhist"
  | "ethiopic"
  | "ethioaa"
  | "coptic"
  | "hebrew"
  | "indian"
  | "islamic-civil"
  | "islamic-tbla"
  | "islamic-umalqura"
  | "japanese"
  | "persian"
  | "roc"
  | "gregory";
```
